package com.fangshi

import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.view.*
import android.view.View.GONE
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
import androidx.core.view.children
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import com.fangshi.adapter.MyRecyclerViewAdapter
import com.fangshi.databinding.FragmentGarageBinding
import com.fangshi.device.Scanner
import com.fangshi.device.createScanner
import com.fangshi.util.SoundPlayer
import com.fangshi.viewmodels.GarageViewModel
import com.fangshi.viewmodels.GarageViewModelFactory
import com.google.android.material.tabs.TabLayout
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext


class GarageFragment : Fragment() {

    private lateinit var binding: FragmentGarageBinding
    private val viewModel: GarageViewModel by viewModels(factoryProducer = {
        val baseUrl = requireActivity().getPreferences(Context.MODE_PRIVATE)
            .getString(KEY, DEFAULT_BASE_URL)
        GarageViewModelFactory(baseUrl!!)
    })
    private var isGoIn = false //当前是出库还是入库
    private val sound: SoundPlayer by lazy {
        SoundPlayer(requireContext())
    }
    private val scanner: Scanner by lazy {
        createScanner(requireContext(), this::onScanBarcode)
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(scanner)
        lifecycle.addObserver(sound)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        setupMenu()
        binding = FragmentGarageBinding.inflate(inflater, container, false)
        return binding.root
    }


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initWidgetListener()
        initObservers()
    }


    override fun onResume() {
        super.onResume()
        (activity as AppCompatActivity).supportActionBar?.title = "槽车出入库登记"
        (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(false)
        if (viewModel.areas.value.isNullOrEmpty())
            viewModel.loadData()
        else
            viewModel.onSwitchArea()
    }

    private fun setupMenu() {
        (requireActivity() as MenuHost).addMenuProvider(object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                menuInflater.inflate(R.menu.main, menu)
            }

            override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
                when (menuItem.itemId) {
                    R.id.history -> {
                        val direction =
                            GarageFragmentDirections.actionGarageFragmentToRecordsFragment()
                        findNavController().navigate(direction)
                    }
                    R.id.manualEntry -> manualDialog(true)
                    R.id.manualExit -> manualDialog(false)
                    R.id.setUrl -> showSetUrlDialog()
                }
                return true
            }
        }, viewLifecycleOwner, Lifecycle.State.RESUMED)
    }

    private fun manualDialog(isGoIn: Boolean) {
        val dialogView = layoutInflater.inflate(R.layout.dialog, null)
        val edit = dialogView.findViewById<EditText>(R.id.dialogInput)

        val goInFunc = DialogInterface.OnClickListener { _, _ ->
            if (viewModel.selectedGarageId.value == null) {
                displayDialog("请先选择要进入的车库")
                return@OnClickListener
            }
            if (edit.text.toString().isEmpty()) {
                displayDialog("请填写槽车号")
                return@OnClickListener
            }
            lifecycleScope.launch {
                val res = withContext(Dispatchers.Default) {
                    viewModel.enterGarageByManual(edit.text.toString())
                }
                displayDialog(res)
            }
        }

        val goOutFunc = DialogInterface.OnClickListener { _, _ ->
            if (viewModel.selectedGarageId.value == null) {
                displayDialog("请先选择车库")
                return@OnClickListener
            }
            if (edit.text.toString().isEmpty()) {
                displayDialog("请填写槽车号")
                return@OnClickListener
            }
            lifecycleScope.launch {
                val res = withContext(Dispatchers.Default) {
                    viewModel.exitGarageByManual(edit.text.toString())
                }
                displayDialog(res)
            }
        }

        AlertDialog.Builder(requireContext())
            .setView(dialogView)
            .setTitle(if (isGoIn) "入库" else "出库")
            .setPositiveButton("确定", if (isGoIn) goInFunc else goOutFunc)
            .setNegativeButton("取消") { dialog, _ -> dialog.dismiss() }
            .show()

    }

    private fun showSetUrlDialog() {
        val dialogView = layoutInflater.inflate(R.layout.dialog, null)
        val edit = dialogView.findViewById<EditText>(R.id.dialogInput)
        val oldBaseUrl = requireActivity().getPreferences(Context.MODE_PRIVATE)
            .getString(KEY, DEFAULT_BASE_URL)
        edit.setText(oldBaseUrl)

        val callback = DialogInterface.OnClickListener { _: DialogInterface, _: Int ->
            val newBaseUrl = edit.text.toString()
            val reg1=Regex("^https?://[0-9]{1,3}(\\.[0-9]{1,3}){3}(:\\d{1,5})?\$")
            val reg2=Regex("^https?://[\\w]+(\\.[\\w]+)*(:\\d{1,5})?$")
            if (!newBaseUrl.matches(reg1)
                && !newBaseUrl.matches(reg2)) {
                Toast.makeText(requireContext(),"地址格式非法",Toast.LENGTH_SHORT).show()
                return@OnClickListener
            }
            if (oldBaseUrl.equals(newBaseUrl)) {
                return@OnClickListener
            }

            val sharedPref = requireActivity().getPreferences(Context.MODE_PRIVATE)
            with(sharedPref.edit()) {
                putString(KEY, newBaseUrl)
                apply()
            }
            viewModel.setBaseUrl(newBaseUrl)
            viewModel.loadData()
        }

        AlertDialog.Builder(requireContext())
            .setView(dialogView)
            .setTitle("地址设置")
            .setPositiveButton("确定", callback)
            .setNegativeButton("取消") { dialog, _ -> dialog.dismiss() }
            .show()
    }


    private suspend fun onScanBarcode(carNo: String) {
        sound.play()
        val info = if (isGoIn) {
            viewModel.enterGarageByScan(carNo)
        } else {
            viewModel.exitGarageByScan(carNo)
        }
        withContext(Dispatchers.Main) {
            displayDialog(info)
        }
    }

    private fun initWidgetListener() {
        binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabSelected(tab: TabLayout.Tab?) {
                viewModel.onAreaSelected(tab?.tag.toString())
            }

            override fun onTabUnselected(tab: TabLayout.Tab?) {
                viewModel.onSwitchArea()
            }

            override fun onTabReselected(tab: TabLayout.Tab?) {
            }
        })
        binding.goInButton.setOnClickListener {
            scanner.startScan()
            isGoIn = true
        }
        binding.goOutButton.setOnClickListener {
            scanner.startScan()
            isGoIn = false
        }
    }

    private fun initObservers() {
        viewModel.areas.observe(viewLifecycleOwner) { areas ->
            val tabLayout = binding.tabLayout
            tabLayout.removeAllTabs()
            for (area in areas) {
                val tab = tabLayout.newTab()
                    .setTag(area.areaName)
                    .setText("区域${area.areaName}")
                    .setIcon(R.drawable.area)
                tabLayout.addTab(tab)
            }
            if (areas.isNotEmpty()) {
                binding.progressBar.visibility = GONE
            }
        }

        viewModel.garagesDisplayed.observe(viewLifecycleOwner) { garages ->
            val adapter = MyRecyclerViewAdapter(garages) { garageId: String ->
                viewModel.onGarageSelected(garageId)
            }
            binding.recyclerView.layoutManager = GridLayoutManager(context, 2)
            binding.recyclerView.adapter = adapter
        }

        viewModel.selectedGarageId.observe(viewLifecycleOwner) {
            binding.goInButton.isEnabled = it != null
            binding.goOutButton.isEnabled = it != null
        }

        viewModel.errMsg.observe(viewLifecycleOwner) {
            it?.let {
                Toast.makeText(requireContext(), it, Toast.LENGTH_LONG).show()
            }
        }
    }

    private fun displayDialog(msg: String) {
        val builder = AlertDialog.Builder(requireContext())
        builder.setTitle("提示")
            .setMessage(msg)
            .create()
            .show()
    }

}